package org.dxy.middleware.dynamic.thread.pool.infrastructure.adapter;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dxy.middleware.dynamic.thread.pool.application.query.repository.AThreadPoolQueryRepository;
import org.dxy.middleware.dynamic.thread.pool.application.view.ThreadPoolView;

import org.dxy.middleware.dynamic.thread.pool.domain.model.ThreadPoolAggregate;
import org.dxy.middleware.dynamic.thread.pool.type.Constants;
import org.redisson.api.RBucket;
import org.redisson.api.RKeys;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

/**
 * @ description:
 * @ author: dxy
 * @ createTime: 2025/10/3 20:24
 */

@Slf4j
@Repository
@RequiredArgsConstructor
public class ThreadPoolQueryRepository implements AThreadPoolQueryRepository {

    private final RedissonClient redissonClient;
    ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public ThreadPoolView findByAppNameAndPoolName(String appName, String poolName) {
        try {
            // 构造 Redis Key
            String key = Constants.runtimeKey(appName, poolName);

            // 获取 Redis Bucket
            RBucket<String> bucket = redissonClient.getBucket(key);

            // 获取 JSON 数据
            String json = bucket.get();
            if (json == null) {
                log.warn("线程池运行时视图不存在 -> key={}", key);
                return null;
            }

            // 反序列化为 ThreadPoolView
            return objectMapper.readValue(json, ThreadPoolView.class);

        } catch (Exception e) {
            log.error("读取线程池运行时视图失败 -> appName={}, poolName={}, cause={}",
                    appName, poolName, e.getMessage(), e);
            throw new RuntimeException("读取线程池运行时视图失败", e);
        }
    }

    @Override
    public List<ThreadPoolView> findAll() {
        List<ThreadPoolView> result = new ArrayList<>();
        try {
            // 1. 获取所有符合规则的 key
            RKeys keys = redissonClient.getKeys();
            Iterable<String> allKeys = keys.getKeysByPattern(Constants.THREAD_POOL_RUNTIME_KEY_GLOB);

            // 2. 遍历 key 并反序列化
            for (String key : allKeys) {
                try {
                    RBucket<String> bucket = redissonClient.getBucket(key);
                    String json = bucket.get();
                    if (json != null) {
                        ThreadPoolView threadPoolView = objectMapper.readValue(json, ThreadPoolView.class);
                        result.add(threadPoolView);
                    }
                } catch (Exception e) {
                    log.error("解析线程池缓存失败，key={}", key, e);
                }
            }
            log.info("查询线程池配置完成，共 {} 条", result.size());
        } catch (Exception e) {
            log.error("查询线程池配置失败", e);
        }
        return result;
    }

    @Override
    public void save(ThreadPoolView view) {
        String key = Constants.runtimeKey(view.getAppName(), view.getThreadPoolName());
        try {
            RBucket<String> bucket = redissonClient.getBucket(key);
            String json = objectMapper.writeValueAsString(view);
            bucket.set(json);
            log.info("保存线程池运行时信息成功 -> key={}", key);
        } catch (Exception e) {
            log.error("保存线程池运行时信息 Redis 失败 -> key: {}, error: {}", key, e.getMessage(), e);
            throw new RuntimeException("Redis 保存失败", e);
        }
    }

    @Override
    public void update(ThreadPoolAggregate threadPoolAggregate) {
        try {
            // 1. 构造 Redis Key
            String key = Constants.runtimeKey(threadPoolAggregate.getAppName(), threadPoolAggregate.getThreadPoolName());

            // 2. 从 Redis 读取已有视图
            RBucket<String> bucket = redissonClient.getBucket(key);
            String json = bucket.get();

            if (json == null || json.isEmpty()) {
                throw new IllegalStateException(String.format(
                        "线程池视图不存在，无法更新 -> appName=%s, poolName=%s",
                        threadPoolAggregate.getAppName(),
                        threadPoolAggregate.getThreadPoolName()
                ));
            }

            // 3. 反序列化
            ThreadPoolView view = objectMapper.readValue(json, ThreadPoolView.class);

            // 4. 更新需要的字段
            view.setCorePoolSize(threadPoolAggregate.getCorePoolSize());
            view.setMaximumPoolSize(threadPoolAggregate.getMaximumPoolSize());

            // 5. 序列化并保存
            String updatedJson = objectMapper.writeValueAsString(view);
            bucket.set(updatedJson);

            log.info("已更新线程池读模型到 Redis -> key: {}, value: {}", key, updatedJson);

        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            throw e; // 保留异常信息，供调用者处理
        } catch (Exception e) {
            log.error("更新线程池读模型失败 -> appName={}, poolName={}, error={}",
                    threadPoolAggregate.getAppName(),
                    threadPoolAggregate.getThreadPoolName(),
                    e.getMessage(), e);
            throw new RuntimeException("更新线程池读模型失败", e);
        }
    }


}
